/*
 * Copyright 2009 rashaguo <rashaguo@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include "servicexml.h"

#include <QFile>
#include <QtXml/QDomDocument>
#include <QtXml/QDomElement>
#include <QtXml/QDomNodeList>
#include <QtXml/QDomNode>

#include "../../utils/logger.h"
#include "../../config/config.h"

#include "../httplikeservice.h"
#include "../activeservicemanager.h"
#include "../httplikeservice.h"


ServiceXml::ServiceXml(std::string xml)
:m_xml(xml), m_type("text/xml"),m_length(0)
{
}

ServiceXml::ServiceXml(QFile &file)
{
    QDomDocument doc;
    if(file.open(QIODevice::ReadOnly))
    {
       LOG_DEBUG("Get xml file successfully");
       if(!doc.setContent(&file))
       {
           LOG_ERROR("Set xml content failed");
           file.close();
       }
       else
       {
           LOG_DEBUG("Set xml content successfully");
           file.close();
       }
    }
    else
    {
        LOG_ERROR("Get xml file failed");
    }

    m_xml = doc.toString().toStdString();
    m_type = "text/xml";
    m_length = 0;
}

ServiceXml::~ServiceXml()
{
    m_xml = "";
}

std::string ServiceXml::preSendProcess()
{
    purgeXml();
    addWebServerInfo();
    LOG_DEBUG("Do process xml result: %s", m_xml.c_str());
    m_length = m_xml.length();
    return m_xml;
}

void ServiceXml::purgeXml()
{
    QDomDocument doc;
    if(!doc.setContent(QString::fromStdString(m_xml)))
    {
        LOG_ERROR("Can not set content for xml");
        return;
    }

    QDomElement root = doc.documentElement();
    QDomNodeList list = root.elementsByTagName(QString::fromUtf8("Service"));
    for(int i = 0; i < list.length(); i++)
    {
        if(list.at(i).toElement().attribute(QString::fromUtf8("enable")) == QString::fromUtf8("false"))
        {
            root.removeChild(list.at(i));
        }
    }

    m_xml = doc.toString().toStdString();
    LOG_DEBUG("Purge xml result: %s", m_xml.c_str());

}

void ServiceXml::addWebServerInfo()
{
    LOG_DEBUG("start add web server info");
    HttpLikeService *webServer = (HttpLikeService*)ActiveServiceManager::getInstance()->getServiceByName("Webserver");
    if(!webServer)
    {
        LOG_DEBUG("Web server is not running");
        return;
    }

    std::string local_ip = webServer->getServerLocalIP();
    std::string local_port = webServer->getServerLocalPort();
    std::string nat_ip = webServer->getServerNatIP();
    std::string nat_port = webServer->getServerNatPort();
    std::string nat = webServer->isNat() ? "true" : "false";

    QDomDocument doc;

    if(!doc.setContent(QString::fromStdString(m_xml)))
    {
        LOG_ERROR("Can not set content for xml");
        return;
    }

    QDomElement root = doc.documentElement();
    QDomNodeList list = root.elementsByTagName(QString::fromUtf8("Service"));
    if(list.isEmpty())
    {
        LOG_DEBUG("Service tag is NULL");
        return;
    }

    QDomNode node;
    QDomElement element;
    for(int i = 0; i < list.length(); i++)
    {
        node = list.at(i);
        if(node.isElement())
        {
            element = node.toElement();
            if(element.attribute(QString::fromUtf8("name")) == QString::fromUtf8("Webserver"))
            {
                element.setAttribute(QString::fromUtf8("server_ip"), QString::fromStdString(local_ip));
                element.setAttribute(QString::fromUtf8("server_port"), QString::fromStdString(local_port));
                element.setAttribute(QString::fromUtf8("nat"), QString::fromStdString(nat));
                element.setAttribute(QString::fromUtf8("nat_ip"), QString::fromStdString(nat_ip));
                element.setAttribute(QString::fromUtf8("nat_port"), QString::fromStdString(nat_port));
                break;
            }
        }
    }

    m_xml = doc.toString().toStdString();
    LOG_DEBUG("Add web server infomation into xml : %s", m_xml.c_str());
    // TODO

}

bool ServiceXml::validXml()
{
    return true;

}

std::string ServiceXml::postReceivedProcess()
{
    xml2html();
    return m_xml;
}

void ServiceXml::xml2html()
{

    QDomDocument doc;
    if(!doc.setContent(QString::fromStdString(m_xml)))
    {
        LOG_ERROR("Can not set content for service xml");
        return;
    }

    QDomNodeList list = doc.elementsByTagName(QString::fromUtf8("Service"));
    if(list.isEmpty())
    {
        LOG_DEBUG("Service list is NULL");
        return;
    }

    QDomNode node;
    QDomElement element;

    std::string remote_ip;
    std::string remote_port;
    std::string remote_nat_ip;
    std::string remote_nat_port;
    bool is_nat = false;

    bool flag = false;
#if 1 //deal with some parameters missed case
    for(int i = 0; i < list.length(); i++)
    {
        if(list.at(i).isElement() && (list.at(i).toElement().attribute(QString::fromUtf8("name")) == QString::fromUtf8("Webserver")))
        {
            element = list.at(i).toElement();
            remote_ip = element.attribute(QString::fromUtf8("server_ip")).toStdString();
            remote_port = element.attribute(QString::fromUtf8("server_port")).toStdString();
            remote_nat_ip = element.attribute(QString::fromUtf8("nat_ip")).toStdString();
            remote_nat_port = element.attribute(QString::fromUtf8("nat_port")).toStdString();
            is_nat = (element.attribute(QString::fromUtf8("nat")).toStdString() == "true") ? true : false;
            flag = true;
            break;
        }
    }
#endif

    std::string html;

    std::string service_name;
    std::string service_url;
    std::string service_desc;
    std::string service_dep;
    bool has_service = false;

    html += "<html>\n<head>\n<link href=\"config/css/style.css\" rel=stylesheet type=\"text/css\">\n</head>\n";

    html += "<body bgcolor=white>\n";
    html += "<p>\n";
    html += "<h1>Service List</h1>\n<ul>\n";

    for(int i = 0; i < list.length(); i++)
    {
        if(list.at(i).isElement() && (list.at(i).toElement().attribute(QString::fromUtf8("name")) != QString::fromUtf8("Webserver")))
        {
            element = list.at(i).toElement();
            service_name = element.attribute(QString::fromUtf8("name")).toStdString();
            service_url = element.attribute(QString::fromUtf8("url")).toStdString();
            service_desc = element.attribute(QString::fromUtf8("description")).toStdString();

            if(element.hasChildNodes())
            {
                service_dep = element.firstChildElement(QString::fromUtf8("Dependence")).attribute(QString::fromUtf8("name")).toStdString();
            }

            //if((ActiveServiceManager::getInstance()->getServiceByName(service_dep)) &&
            //        !ActiveServiceManager::getInstance()->getServiceByName(service_dep)->isServerRunning())
           // {
                //html += "<li><a>Service is not aviable, please contact your friends</a>\n";
            //    continue;
           // }
            html += "<li><a href=\"";
            if(!is_nat)
            {
                html += "httpu://" + remote_ip + ":" + remote_port +
                        service_url + "\">" + service_name + "</a> -" + service_desc + "\n";
            }
            else
            {
                //TODO
                //Deal with the NAT, same NAT cases
                //here we suppose under same Nat and set it none nat;
            }

        }
    }
    html += "</ul>\n</p>\n";
    //return html;
    m_xml = html;


}
